<?php
require_once("Node.php");

class XForms_Core extends Node{
  protected $xforms_processor;
  protected $attributes=array();
  protected $childNodes=array();
  protected $nodesetIndex=0;
  public $node;
  public $document;
    //3.2.1 -> id **
  function getId(){
    return $this->attributes["id"];
  }
  function getAttribute($name){
    return $this->attributes[$name];
  }
  function setAttribute($name, $value){
    $this->attributes[$name] = $value;
  }
  //TODO: 3.2.2 Linking Attributes
  //3.2.3 Single-Node Binding Attributes
  function getRef(){
    $ctx = $this->getEvaluationContext();
    $exp = $this->getAttribute("ref");
    return $this->xforms_processor->findBinding($exp, $ctx);
  }
  function getModel(){
    $ctx = $this->getEvaluationContext();
    $exp = $this->node->getAttribute("model");
    if($exp) {
      return $this->xforms_processor->findBinding($exp, $ctx);
    } else {
      return $this->xforms_processor->getDefaultModel();
    }
  }
  function getBind(){
    /*$ctx = $this->getEvaluationContext();
    $exp = $this->getAttribute("bind");
    return $this->xforms_processor->findBinding($exp, $ctx);*/
    return $this->xforms_processor->getElementById($this->getAttribute("bind"));
  }
  //7.2 Evaluation Context->1
  function getEvaluationContext(){
    $xp = $this->xforms_processor;
    $xparent = $xp->findXParentElement($this->node, 'XForms_Core');
    if($xparent) {
      if($xparent instanceof Xforms_model) {
        return $xp->getFirstElement($xp->getDefaultInstance($xparent->node));
      } else {
        $binding = $xparent->getBinding();
        if(!isset($binding)) $binding = $xparent->getEvaluationContext();
        return $binding;
      }
    } else {
      return $xp->getFirstElement($xp->getDefaultInstance($xp->getDefaultModel()));
    }
    //TODO: create model class
    /*if($outermost->parentNode->nodeName=="model") {
      return $xp->getFirstElement($xp->getDefaultInstance($outermost->parentNode));
    } else {
      return $xp->getFirstElement($xp->getDefaultInstance($xp->getDefaultModel()));
    }*/
  }
  function getBinding(){
    if(isset($this->attributes["bind"])) {
      return $this->getBind();
    } elseif(isset($this->attributes["model"])) {
      return $this->getModel();
    } elseif(isset($this->attributes["nodeset"])) {
      $ctx = $this->getEvaluationContext();
      $exp = $this->getAttribute("nodeset");
      return $this->xforms_processor->findBinding($exp, $ctx, $this->nodesetIndex);
    } elseif(isset($this->attributes["ref"])) {
      return $this->getRef();
    } else {
      return null;
    }
  }
  function getBindings(){
    if(isset($this->attributes["nodeset"])) {
      $ctx = $this->getEvaluationContext();
      $exp = $this->getAttribute("nodeset");
      return $this->xforms_processor->findBindings($exp, $ctx);
    } else {
      return null;
    }
  }
  function getValue(){
    $binding = $this->getBinding();
    $xp = $this->xforms_processor;
    if($binding) {
      $xbinding = $xp->findXElement($binding);
      if($xbinding instanceof XForms_Core){
        return $xbinding->getValue();
      } else {
        return $binding->nodeValue;
      }
    } else {
      $xvalue = $this->node->getElementsByTagName("xforms:value");
      if($xvalue->length>0) {
        $xbinding = $xp->findXElement($xvalue->item(0));
        if($xbinding instanceof XForms_Core) {
          return $xbinding->getValue();
        } else {
          return $binding->nodeValue;
        }
      } elseif($this->node->getAttribute("value")) {
        return $this->evalAttribute("value");
        //return $this->node->getAttribute("value");
      } else {
        return $this->node->nodeValue;
      }
    }
  }
  function evaluateXPath($exp, $multipleNode=null) {
    $ctx = $this->getEvaluationContext();
    if(isset($multipleNode) && $multipleNode) return $this->xforms_processor->findBindings($exp, $ctx);
    else return $this->xforms_processor->findBinding($exp, $ctx);
  }
  function evalAttribute($attribute, $multipleNode=null){
    $a = $this->node->getAttribute($attribute);
    if($attribute=="nodeset" && !isset($multipleNode)) $multipleNode = true;
    if($a) {
      $a = $this->evaluateXPath("php:function('xpath_encode',$a)", $multipleNode);
      if($a instanceof DOMNode){
        $a = $a->nodeValue;
        if(substr($a,0,2)=='$&') {
          $a = unserialize(substr($a,2));
        }
      }
    }
    return $a;
  }
}
